package cn.ac.radi.userver.waste.model;


import cn.ac.radi.userver.model.wasteyard.minesafety.MineSafetyEvaluator;
import cn.ac.radi.userver.waste.constant.CoalSafetyEvaluateTypeConstant;
import cn.ac.radi.userver.waste.constant.ResultStateConstant;
import cn.ac.radi.userver.waste.entity.GDValueProcessResult;
import cn.ac.radi.userver.waste.entity.ValueProcessParam;
import cn.ac.radi.userver.waste.entity.ValueProcessResult;
import com.mathworks.toolbox.javabuilder.MWNumericArray;
import org.slf4j.Logger;
import org.springframework.core.env.Environment;

import java.io.File;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class CoalSafetyModel {

    private String uuid = "";
    private String inputFolder = "";
    private String resultFolder = "";
    private String reportFolder = "";

    private String reportWebPath = "";

    private Environment env = null;
    private Logger logger = null;

    private String errorMessage = "";
    private static String FILE_NOT_EXIST_ERROR_FORMAT = "[{path}]不存在";

    private boolean state = true;

    public CoalSafetyModel(Environment env, Logger logger){
        this.env = env;
        this.logger = logger;
    }

    public boolean isSuccess() {
        return state;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getInputFolder() {
        if(inputFolder.isEmpty()){
            inputFolder = env.getProperty("userver.model.4_4.coal_safety.input");
        }
        return inputFolder;
    }

    public String getResultFolder() {
        if(resultFolder.isEmpty()){
            resultFolder = env.getProperty("userver.model.4_4.coal_safety.output");
        }
        return resultFolder;
    }

    public String getReportFolder() {
        if(reportFolder.isEmpty()){
            reportFolder = env.getProperty("userver.model.4_4.coal_safety.report");
        }
        return reportFolder;
    }

    private String getWebHomePath(){
        return env.getProperty("userver.env.web_home");
    }

    public String makeInputFilePath(String fileName){
        return Paths.get(this.getInputFolder(), fileName).toString();
    }

    private String makeUniqueFileName(String fileName, String uuid){
        final String FILENAME_TEMPLATE = "{uuid}_{fileName}";
        return FILENAME_TEMPLATE.replace("{uuid}", uuid).replace("{fileName}", fileName);
    }

    public String makeResultFilePath(String fileName){
        return Paths.get(this.getResultFolder(), fileName).toString();
    }

    public String makeReportFilePath(String fileName){
        return Paths.get(this.getReportFolder(), fileName).toString();
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    /**
     * 日期选择
     * @param start
     * @param end
     * @return
     */
    public boolean runDateSelect(Date start, Date end){

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");

        String WYfile = this.makeInputFilePath("8.22-11.11.csv");      //"H:/temp/gyy/11120/data/8.22-11.11.csv";
        String WDfile = this.makeInputFilePath("WD.xlsx");             //"H:/temp/gyy/11120/data/WD.xlsx";
        String YLfile = this.makeInputFilePath("YL.csv");              //"H:/temp/gyy/11120/data/YL.csv";
        String datastar=sdf.format(start);                                      //"2021年09月20日";
        String dataend=sdf.format(end);                                         //"2021年10月10日";
        String savepath=this.getResultFolder();                                 //"H:/temp/gyy/11120/result";
        int numReturns = 5;

        logger.info("\t[WYfile]:" + WYfile);
        logger.info("\t[WDfile]:" + WDfile);
        logger.info("\t[YLfile]:" + YLfile);
        logger.info("\t[datastar]:" + datastar);
        logger.info("\t[datastar]:" + datastar);
        logger.info("\t[savepath]:" + savepath);

        if(!checkFile(WYfile)){
            state = false;
            return false;
        }
        if(!checkFile(WDfile)){
            state = false;
            return false;
        }
        if(!checkFile(YLfile)){
            state = false;
            return false;
        }

        boolean ret = true;
        MineSafetyEvaluator mse = null;
        try{
            logger.info("====  line 102 ====");
            mse = new MineSafetyEvaluator();
            logger.info("====  line 104 ====");
            if(mse==null){
                logger.info("====  line 106 ====");
                logger.error("创建MineSafetyEvaluator对象失败");
            }
            else{
                logger.info("====  line 110 ====");
                Object[] objs = mse.DateSelect(numReturns, WYfile,WDfile,YLfile,datastar,dataend,savepath,uuid);
                logger.info("====  line 112 ====");
            }
            state = true;
        }
        catch (Exception e){
            e.printStackTrace();
            state = false;
        }
        finally {
            logger.info("====  line 120 ====");
            return state;
        }
    }

    /**
     * 检查路径是否合法，路径是否是文件
     * @param path
     * @return
     */
    public boolean checkFile(String path){
        File file = new File(path);
        if(!file.exists()){
            errorMessage = FILE_NOT_EXIST_ERROR_FORMAT.replace("{path}",path);
            logger.error(errorMessage);
            return false;
        }
        return file.isFile();
    }

    /**
     * 查路径是否合法，路径是否是目录
     * @param path
     * @return
     */
    public boolean checkFolder(String path){
        File file = new File(path);
        if(!file.exists()){
            errorMessage = FILE_NOT_EXIST_ERROR_FORMAT.replace("{path}",path);
            logger.error(errorMessage);
            return false;
        }
        return file.isDirectory();
    }

    public List<ValueProcessResult> runEvaluates(List<ValueProcessParam> params){

        ValueProcessResult result = null;
        List<ValueProcessResult> results = new ArrayList<>();
        ValueProcessParam param = null;
        int count = params.size();
        for(int i=0; i<count; i++){
            param = params.get(i);
            String type = param.getType();
            switch (type){
                case CoalSafetyEvaluateTypeConstant.HORIZONTAL:{
                    GDValueProcessResult ret = runEvaluateHorizontal(param.getFile(), param.getUuid());
                    if(ret!=null){
                        results.add(ret);
                    }
                    break;
                }
                case CoalSafetyEvaluateTypeConstant.VERTICAL:{
                    result = runEvaluateVertical(param.getFile(), param.getUuid());
                    if(result!=null){
                        results.add(result);
                    }
                    break;
                }
                case CoalSafetyEvaluateTypeConstant.BURN:{
                    result = runEvaluateBurn(param.getFile(), param.getUuid());
                    if(result!=null){
                        results.add(result);
                    }
                    break;
                }
            }
        }

        return results;
    }

    /**
     * @param fileName(DayGD.xlsx)
     * @return
     */
    private GDValueProcessResult runEvaluateHorizontal(String fileName, String uuid){

        logger.info("\t水平位移: ");
        logger.info("\t[SessionID]: "+uuid);

        GDValueProcessResult result = new GDValueProcessResult();
        result.setType(CoalSafetyEvaluateTypeConstant.HORIZONTAL);

        String uniqueFileName = this.makeUniqueFileName(fileName, uuid);
        String DayGDFile = this.makeResultFilePath(uniqueFileName);

        logger.info("\t[DayGDFile]:" + DayGDFile);
        if(!checkFile(DayGDFile)){
            state = false;
            result.setState(ResultStateConstant.FAILURE);
            return result;
        }

        int numReturns = 4;
        MineSafetyEvaluator mse = null;

        logger.info("安全评价：水平位移--开始--");
        try{
            mse = new MineSafetyEvaluator();
            Object[] objs = mse.Value_GDprocess(numReturns, DayGDFile, uuid);
            //Object[] objs = mse.Value_GDprocess(numReturns, DayGDFile);
            if(objs.length==numReturns){
                MWNumericArray mwValue = (MWNumericArray)(objs[0]);
                result.setS(mwValue.getFloat());

                mwValue = (MWNumericArray)(objs[1]);
                result.setV(mwValue.getFloat());

                mwValue = (MWNumericArray)(objs[2]);
                result.setDetv(mwValue.getFloat());

                mwValue = (MWNumericArray)(objs[3]);
                result.setAlpha(mwValue.getFloat());

                result.setState(ResultStateConstant.SUCCESS);

            }
            else{
                result.setState(ResultStateConstant.FAILURE);
            }
        }
        catch (Exception e){
            e.printStackTrace();
            result.setState(ResultStateConstant.FAILURE);
        }
        finally {
            logger.info("安全评价：水平位移--结束--");
            return result;
        }
    }

    /**
     * @param fileName(DayDP.xlsx)
     * @return
     */
    private ValueProcessResult runEvaluateVertical(String fileName, String uuid){

        ValueProcessResult result = new ValueProcessResult();
        result.setType(CoalSafetyEvaluateTypeConstant.VERTICAL);

        String uniqueFileName = this.makeUniqueFileName(fileName, uuid);
        String DayDPFile = this.makeResultFilePath(uniqueFileName);
        //String DayDPFile = this.makeResultFilePath(fileName);
        logger.info("\t[DayDPFile]:" + DayDPFile);
        if(!checkFile(DayDPFile)){
            state = false;
            result.setState(ResultStateConstant.FAILURE);
            return result;
        }

        int numReturns = 1;
        MineSafetyEvaluator mse = null;

        logger.info("安全评价：垂直位移--开始--");
        try{
            mse = new MineSafetyEvaluator();
            Object[] objs = mse.Value_DPprocess(numReturns, DayDPFile, uuid);
            if(objs.length==numReturns){
                MWNumericArray mwValue = (MWNumericArray)(objs[0]);
                float value = mwValue.getFloat();
                result.setState(ResultStateConstant.SUCCESS);
                result.setfValue(value);
            }
            else{
                result.setState(ResultStateConstant.FAILURE);
            }

        }
        catch (Exception e){
            e.printStackTrace();
            result.setState(ResultStateConstant.FAILURE);
        }
        finally {
            logger.info("安全评价：垂直位移--结束--");
            return result;
        }
    }

    /**
     * @param fileName(DayWD.xlsx)
     * @return
     */
    private ValueProcessResult runEvaluateBurn(String fileName, String uuid){
        ValueProcessResult result = new ValueProcessResult();
        result.setType(CoalSafetyEvaluateTypeConstant.BURN);

        String uniqueFileName = this.makeUniqueFileName(fileName, uuid);
        String DayWDFile = this.makeResultFilePath(uniqueFileName);
        //String DayWDFile = this.makeResultFilePath(fileName);
        logger.info("\t[DayDPFile]:" + DayWDFile);
        if(!checkFile(DayWDFile)){
            state = false;
            result.setState(ResultStateConstant.FAILURE);
            return result;
        }

        int numReturns = 1;
        MineSafetyEvaluator mse = null;

        logger.info("安全评价：自燃风险--开始--");

        try{
            mse = new MineSafetyEvaluator();
            Object[] objs = mse.Value_WDprocess(numReturns, DayWDFile, uuid);
            if(objs.length==numReturns){
                MWNumericArray mwValue = (MWNumericArray)(objs[0]);
                float value = mwValue.getFloat();
                result.setState(ResultStateConstant.SUCCESS);
                result.setfValue(value);
            }
            else{
                result.setState(ResultStateConstant.FAILURE);
            }
        }
        catch (Exception e){
            e.printStackTrace();
            result.setState(ResultStateConstant.FAILURE);
        }
        finally {
            logger.info("安全评价：自燃风险--结束--");

            return result;
        }
    }

    public boolean runCreateReport(){

        String uuid = this.getUuid();
        String input = this.getResultFolder();
        String output = this.getReportFolder();
        String reportName = this.makeReportFileName();
        String reportPath = this.makeReportPath(reportName);

        logger.info("安全评价：生成报表--开始--");

        MineSafetyEvaluator mse = null;
        try{
            mse = new MineSafetyEvaluator();
            mse.creatReport(input, output, reportName, uuid);
            reportWebPath = this.makeReportWebPath(reportName);
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            logger.info("安全评价：生成报表--结束--");
        }

        return true;
    }

    private String makeReportFileName(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String str = sdf.format(new Date());
        String fileName = str + ".doc";

        return fileName;
    }

    private String makeReportPath(String fileName){

        String reportFolder = this.getReportFolder();
        return Paths.get(reportFolder, fileName).toString();
    }

    private String makeReportWebPath(String fileName){
        String reportPath = makeReportPath(fileName).replace("\\", "/");
        String webRoot = getWebHomePath();;
        return reportPath.replace(webRoot, "");
    }

    public String getReportWebPath(){
        return this.reportWebPath;
    }

}
